package com.link.base.core.basic.util;

import com.alibaba.fastjson.JSONObject;
import com.link.base.wechat.basic.util.WeixinHttpUtil;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.util.HttpRequestUtil;
import com.link.core.util.PropertyUtil;
import com.link.core.util.RedisUtil;
import com.link.core.util.StringUtils;
import com.link.core.util.redisclient.LinkRedisClient;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.net.URL;
import java.net.URLDecoder;
import java.security.MessageDigest;
import java.util.Formatter;
import java.util.Random;

public class DingDingUtil {

    private static final Logger logger = LogManager.getLogger(DingDingUtil.class);

    public static String DING_TALK_TOKEN_URL = "https://oapi.dingtalk.com/gettoken";

    public static String DING_USER_INFO = "https://oapi.dingtalk.com/user/getuserinfo";

    public static String DING_USER_INFO_V2 = "https://oapi.dingtalk.com/topapi/v2/user/getuserinfo";

    public static String DING_USER_DETAIL = "https://oapi.dingtalk.com/topapi/v2/user/get";

    public static String DING_JSAPI_TICKET = "https://oapi.dingtalk.com/get_jsapi_ticket";

    public static String getToken() throws Exception {

        LinkRedisClient jedis = null;
        String accessToken = "";
        String key = "ding_access_token";
        try {
            jedis = RedisUtil.getJedis();
            accessToken = jedis.get("ding_access_token");
            if (StringUtils.isBlank(accessToken)) {
                String appkey = PropertyUtil.getCommonProperty("dingappkey");
                String appsecret = PropertyUtil.getCommonProperty("dingappsecret");
                String requestUrl = DING_TALK_TOKEN_URL + "?appkey=" + appkey
                        + "&appsecret=" + appsecret;

                System.out.println(requestUrl);
                JSONObject jsonObject = WeixinHttpUtil.doGet(requestUrl);
                if (jsonObject != null && "0".equals(jsonObject.getString("errcode"))) {
                    accessToken = jsonObject.getString("access_token");
                    loadTokenToRedis("ding_access_token",accessToken,7200);
                } else {
                    throw new BasicServiceException("通过dingappkey" + appkey + "获取API相应参数失败！");
                }
            }
        } catch (Exception e) {
            throw e;
        } finally {
            RedisUtil.returnResource(jedis);
        }
        return accessToken;
    }

    public static void loadTokenToRedis(String key, String tokenValue,int num) throws Exception {
        LinkRedisClient jedis = RedisUtil.getJedis();
        try {
            //CoreUser user = UserUtil.getUser();
            jedis.del(key);
            jedis.set(key, tokenValue,"NX", "EX", num);
        } catch (Exception e) {
            throw e;
        } finally {
            RedisUtil.returnResource(jedis);
        }
    }

    public static JSONObject getUserId(String accessToken,String code) throws Exception {
        JSONObject jsonObject = null;
        if (StringUtils.isBlank(accessToken)) {
            accessToken = getToken();
        }
        String requestUrl = DING_USER_INFO + "?access_token=" + accessToken
                + "&code=" + code;
        jsonObject = WeixinHttpUtil.doGet(requestUrl);
        if (jsonObject == null ) {
            throw new BasicServiceException("通过access_token=" + accessToken
                    + "&code=" + code + "获取钉钉用户信息失败！");
        } else if ("0".equals(jsonObject.getString("errcode"))) {
            throw new BasicServiceException("通过access_token=" + accessToken
                    + "&code=" + code + "获取钉钉用户信息失败:" + jsonObject.getString("errmsg"));
        }
        return jsonObject;
    }

    public static JSONObject getUserIdV2(String accessToken,String code) throws Exception {
        JSONObject result = null;
        if (StringUtils.isBlank(accessToken)) {
            accessToken = getToken();
        }
        String requestUrl = DING_USER_INFO_V2 + "?access_token=" + accessToken;
        JSONObject queryParam = new JSONObject();
        queryParam.put("code",code);
        String responseStr = HttpRequestUtil.sendPost(requestUrl,queryParam.toJSONString(),"");
        JSONObject jsonObject = JSONObject.parseObject(responseStr);
        logger.info("返回用户Id详情：" + jsonObject.toJSONString());
        if (jsonObject == null ) {
            throw new BasicServiceException("通过access_token=" + accessToken
                    + "&code=" + code + "获取钉钉用户信息失败！");
        } else if ("0".equals(jsonObject.getString("errcode")) && jsonObject.getJSONObject("result") != null) {
            result = jsonObject.getJSONObject("result");
        } else {
            throw new BasicServiceException("通过access_token=" + accessToken
                    + "&code=" + code + "获取钉钉用户信息失败1111:" + jsonObject.getString("errmsg"));
        }
        return result;
    }

    public static JSONObject getUserDetail(String accessToken,String userid,String language) throws Exception {
        JSONObject result = null;
        if (StringUtils.isBlank(accessToken)) {
            accessToken = getToken();
        }
        String requestUrl = DING_USER_DETAIL + "?access_token=" + accessToken;
        JSONObject queryParam = new JSONObject();
        queryParam.put("userid",userid);
        queryParam.put("language",language);
        String responseStr = HttpRequestUtil.sendPost(requestUrl,queryParam.toJSONString(),"");
        JSONObject jsonObject = JSONObject.parseObject(responseStr);
        logger.info("返回用户详情：" + jsonObject.toJSONString());
        if (jsonObject == null ) {
            throw new BasicServiceException("通过access_token=" + accessToken
                    + "&userid=" + userid + "获取钉钉用户信息失败！");
        } else if (!"0".equals(jsonObject.getString("errcode"))) {
            throw new BasicServiceException("通过access_token=" + accessToken
                    + "&userid=" + userid + "获取钉钉用户信息失败22222:" + jsonObject.getString("errmsg"));
        } else if (jsonObject.get("result") != null) {
            result = jsonObject.getJSONObject("result");
        }
        return result;
    }

    public static String getJsapiTicket(String accessToken,String url) throws Exception {
        String result = null;
        LinkRedisClient jedis = null;
        try {
            jedis = RedisUtil.getJedis();
            String key = "jsapi-" + url;
            result = jedis.get(key);
            if (StringUtils.isBlank(result)) {
                if (StringUtils.isBlank(accessToken)) {
                    accessToken = getToken();
                }
                String requestUrl = DING_JSAPI_TICKET + "?access_token=" + accessToken;
                JSONObject jsonObject = WeixinHttpUtil.doGet(requestUrl);
                logger.info("返回jsapi_ticket详情：" + jsonObject.toJSONString());
                if (jsonObject == null ) {
                    throw new BasicServiceException("通过access_token=" + accessToken + "获取jsapi_ticket信息失败！");
                } else if (!"0".equals(jsonObject.getString("errcode"))) {
                    throw new BasicServiceException("通过access_token=" + accessToken + "获取jsapi_ticket信息失败:" + jsonObject.getString("errmsg"));
                } else if (jsonObject.get("ticket") != null) {
                    result = jsonObject.getString("ticket");
                    loadTokenToRedis(key,result,7200);
                }
            }
        } catch (Exception e) {
            throw e;
        } finally {
            RedisUtil.returnResource(jedis);
        }


        return result;
    }

    /**
     * 计算dd.config的签名参数
     *
     * @param jsticket  通过微应用appKey获取的jsticket
     * @param nonceStr  自定义固定字符串
     * @param timeStamp 当前时间戳
     * @param url       调用dd.config的当前页面URL
     * @return
     * @throws Exception
     */
    public static String sign(String jsticket, String nonceStr, long timeStamp, String url) throws Exception {
        String plain = "jsapi_ticket=" + jsticket + "&noncestr=" + nonceStr + "&timestamp=" + String.valueOf(timeStamp)
                + "&url=" + decodeUrl(url);
        try {
            MessageDigest sha1 = MessageDigest.getInstance("SHA-256");
            sha1.reset();
            sha1.update(plain.getBytes("UTF-8"));
            return byteToHex(sha1.digest());
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    }

    // 字节数组转化成十六进制字符串
    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash) {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

    /**
     * 因为ios端上传递的url是encode过的，android是原始的url。开发者使用的也是原始url,
     * 所以需要把参数进行一般urlDecode
     *
     * @param url
     * @return
     * @throws Exception
     */
    private static String decodeUrl(String url) throws Exception {
        URL urler = new URL(url);
        StringBuilder urlBuffer = new StringBuilder();
        urlBuffer.append(urler.getProtocol());
        urlBuffer.append(":");
        if (urler.getAuthority() != null && urler.getAuthority().length() > 0) {
            urlBuffer.append("//");
            urlBuffer.append(urler.getAuthority());
        }
        if (urler.getPath() != null) {
            urlBuffer.append(urler.getPath());
        }
        if (urler.getQuery() != null) {
            urlBuffer.append('?');
            urlBuffer.append(URLDecoder.decode(urler.getQuery(), "utf-8"));
        }
        return urlBuffer.toString();
    }

    public static String getRandomStr(int count) {
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < count; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

}
